package com.yunyilian8.www.jokeapp.utils;

import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.Environment;
import android.text.TextUtils;

import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * @author qiujunqi
 * @ClassName: BitmapUtil
 * @Description: 图片工具类
 * @date 2015年5月26日 上午10:52:11
 */
public class BitmapUtil {

    /**
     * 从指定文件当中获取指定比例的图片
     *
     * @param path
     * @param scale
     * @return
     */
    public static Bitmap getBitmap(String path, int scale) {
        Options opts = new Options();
        opts.inSampleSize = scale;
        return BitmapFactory.decodeFile(path, opts);
    }

    /**
     * 从指定文件当中获取图片
     *
     * @param path
     * @return
     */
    public static Bitmap getBitmap(String path) {
        Options options = new Options();
        options.inSampleSize = 2;
        return BitmapFactory.decodeFile(path, options);
    }

    /**
     * 从指定文件当中获取指定宽高的图片
     *
     * @param path
     * @param width
     * @param height
     * @return
     */
    public static Bitmap getBitmap(String path, int width, int height) {
        Bitmap bm = null;
        Options opts = new Options();
        opts.inJustDecodeBounds = true;
        bm = BitmapFactory.decodeFile(path);
        int x = opts.outWidth / width;
        int y = opts.outHeight / height;
        opts.inSampleSize = x > y ? x : y;
        opts.inJustDecodeBounds = false;
        bm = BitmapFactory.decodeFile(path);
        return bm;
    }

    /**
     * 字节数组按比例返回图片
     *
     * @param data
     * @param scale
     * @return
     */
    public static Bitmap getBitmap(byte[] data, int scale) {
        Options opts = new Options();
        opts.inSampleSize = scale;
        return BitmapFactory.decodeByteArray(data, 0, data.length, opts);
    }

    /**
     * 字节数组返回原图片
     *
     * @param data
     * @param scale
     * @return
     */
    public static Bitmap getBitmap(byte[] data) {
        return BitmapFactory.decodeByteArray(data, 0, data.length);
    }

    /**
     * 字节数组按长和宽返回图片
     *
     * @param data
     * @param width
     * @param height
     * @return
     */
    public static Bitmap getBitmap(byte[] data, int width, int height) {
        Options opts = new Options();
        opts.inJustDecodeBounds = true;
        BitmapFactory.decodeByteArray(data, 0, data.length, opts);
        int x = opts.outWidth / width;
        int y = opts.outHeight / height;
        int scale = x > y ? x : y;
        return getBitmap(data, scale);
    }

    /**
     * 指定流得到图片
     *
     * @param in
     * @return
     */
    public static Bitmap getBitmap(InputStream in) {
        return BitmapFactory.decodeStream(in);
    }

    /**
     * 保存图片到指定位置
     *
     * @param bm
     * @param path
     */
    public static void save(Bitmap bm, String path) {
        OutputStream out = null;

        try {
            File file = new File(path);
            if (file.getParentFile() != null) {
                if (!file.getParentFile().exists()) {
                    file.getParentFile().mkdirs();
                }
                if (!file.exists())
                    file.createNewFile();

                out = new BufferedOutputStream(new FileOutputStream(file));
                bm.compress(CompressFormat.JPEG, 100, out);
            }

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    }

    /**
     * 得到圆角图片
     *
     * @param bitmap
     * @param roundPx
     * @return
     */
    public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, float roundPx) {
        int w = bitmap.getWidth();
        int h = bitmap.getHeight();
        Bitmap output = Bitmap.createBitmap(w, h, Config.ARGB_8888);
        Canvas canvas = new Canvas(output);
        final int color = 0xff424242;
        final Paint paint = new Paint();
        final Rect rect = new Rect(0, 0, w, h);
        final RectF rectF = new RectF(rect);
        paint.setAntiAlias(true);
        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(color);
        canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
        paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
        canvas.drawBitmap(bitmap, rect, rect, paint);
        return output;
    }

    /**
     * 返回drawable
     *
     * @param context
     * @param bitmap
     * @return
     */
    public static BitmapDrawable getDrawable(Context context, Bitmap bitmap) {
        return new BitmapDrawable(context.getResources(), bitmap);
    }

    /**
     * 返回SD卡根目录
     */
    public static String getSDRootPath() {
        File sdDir = null;
        boolean sdCardExist = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED); // 判断sd卡是否存在
        if (sdCardExist) {
            sdDir = Environment.getExternalStorageDirectory();// 获取跟目录
            return sdDir.toString();
        }
        return null;
    }

    /**
     * 将Bitmap存入文件
     *
     * @param bitmap
     * @param filePath
     * @return void
     * @Title: saveDrawableToCache
     * @date 2012-12-14 上午9:27:38
     */
    public static void saveDrawableToCache(Bitmap bitmap, String filePath) {
        OutputStream outStream = null;
        try {
            File file = new File(filePath);
            file.createNewFile();
            outStream = new BufferedOutputStream(new FileOutputStream(file));
            bitmap.compress(CompressFormat.JPEG, 100, outStream);
            outStream.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (outStream != null) {
                try {
                    outStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * Bitmap → byte[]
     *
     * @param bm
     * @return
     */
    public static byte[] Bitmap2Bytes(Bitmap bm) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bm.compress(CompressFormat.JPEG, 30, baos);
        byte[] b = baos.toByteArray();
        if (!bm.isRecycled()) {
            bm.isRecycled();
            System.gc();
        }
        return b;
    }

    /**
     * 按比例缩放大小
     *
     * @param cr
     * @param uri
     * @param size
     * @return
     */
    public static Bitmap revitionImageSize(ContentResolver cr, Uri uri, int size) {
        // 取得图片
        InputStream temp = null;
        Bitmap bitmap = null;
        try {
            temp = cr.openInputStream(uri);
            Options options = new Options();
            // 这个参数代表，不为bitmap分配内存空间，只记录一些该图片的信息（例如图片大小），说白了就是为了内存优化
            options.inJustDecodeBounds = true;
            // 通过创建图片的方式，取得options的内容（这里就是利用了java的地址传递来赋值）
            BitmapFactory.decodeStream(temp, null, options);
            // 关闭流
            temp.close();
            // 生成压缩的图片
            int i = 0;

            while (true) {
                // 这一步是根据要设置的大小，使宽和高都能满足
                if ((options.outWidth >> i <= size) && (options.outHeight >> i <= size)) {
                    // 重新取得流，注意：这里一定要再次加载，不能二次使用之前的流！
                    temp = cr.openInputStream(uri);
                    // 这个参数表示 新生成的图片为原始图片的几分之一。
                    options.inSampleSize = (int) Math.pow(2.0D, i);
                    // 这里之前设置为了true，所以要改为false，否则就创建不出图片
                    options.inJustDecodeBounds = false;

                    bitmap = BitmapFactory.decodeStream(temp, null, options);
                    break;
                }
                i += 1;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                temp.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return bitmap;
    }

    /**
     * 按大小比例不断的压缩
     *
     * @param image
     * @param size
     * @return
     */
    @SuppressWarnings("unused")
    public static Bitmap comp(Bitmap image, int size) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        image.compress(CompressFormat.JPEG, 100, baos);
        if (baos.toByteArray().length / 1024 > size) {// 判断如果图片大于1M,进行压缩避免在生成图片（BitmapFactory.decodeStream）时溢出
            baos.reset();// 重置baos即清空baos
            image.compress(CompressFormat.JPEG, 50, baos);// 这里压缩50%，把压缩后的数据存放到baos中
        }
        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
        Options newOpts = new Options();
        // 开始读入图片，此时把options.inJustDecodeBounds 设回true了
        newOpts.inJustDecodeBounds = true;
        Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, newOpts);
        newOpts.inJustDecodeBounds = false;
        int w = newOpts.outWidth;
        int h = newOpts.outHeight;
        // 现在主流手机比较多是800*480分辨率，所以高和宽我们设置为
        // int hh = resolution;//这里设置高度为800f
        // int ww = resolution;//这里设置宽度为480f
        // 缩放比。由于是固定比例缩放，只用高或者宽其中一个数据进行计算即可
        int be = 1;// be=1表示不缩放
        // if (w > h && w > ww) {//如果宽度大的话根据宽度固定大小缩放
        // be = (int) (newOpts.outWidth / ww);
        // } else if (w < h && h > hh) {//如果高度高的话根据宽度固定大小缩放
        // be = (int) (newOpts.outHeight / hh);
        // }
        // if (be <= 0)
        // be = 1;
        newOpts.inSampleSize = be;// 设置缩放比例
        // 重新读入图片，注意此时已经把options.inJustDecodeBounds 设回false了
        isBm = new ByteArrayInputStream(baos.toByteArray());
        bitmap = BitmapFactory.decodeStream(isBm, null, newOpts);
        return compressImage(bitmap, size);// 压缩好比例大小后再进行质量压缩
    }

    public static Bitmap compressImage(Bitmap image, int size) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        image.compress(CompressFormat.JPEG, 100, baos);// 质量压缩方法，这里100表示不压缩，把压缩后的数据存放到baos中
        int options = 50;
        while (baos.toByteArray().length / 1024 > size && options > 0) { // 循环判断如果压缩后图片是否大于100kb,大于继续压缩
            baos.reset();// 重置baos即清空baos
            image.compress(CompressFormat.JPEG, options, baos);// 这里压缩options%，把压缩后的数据存放到baos中
            options -= 10;// 每次都减少10
        }
        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());// 把压缩后的数据baos存放到ByteArrayInputStream中
        Options ops = new Options();
        ops.inSampleSize = 2;
        Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, ops);// 把ByteArrayInputStream数据生成图片
        return bitmap;
    }

    public static byte[] compressImageByte(Bitmap image, int size) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        image.compress(CompressFormat.JPEG, 100, baos);// 质量压缩方法，这里100表示不压缩，把压缩后的数据存放到baos中
        // int options = 100;
        // int minOptions = 80;
        // if(baos.toByteArray().length / 1024 > 1024){
        // minOptions = 40;
        // }
        // while (baos.toByteArray().length / 1024 > size&&options>minOptions) {
        // // 循环判断如果压缩后图片是否大于100kb,大于继续压缩
        // baos.reset();// 重置baos即清空baos
        // image.compress(Bitmap.CompressFormat.JPEG, options, baos);//
        // 这里压缩options%，把压缩后的数据存放到baos中
        // options -= 10;// 每次都减少10
        // }
        return baos.toByteArray();
    }

    /**
     * 计算图片的缩放值
     *
     * @param options
     * @param reqWidth
     * @param reqHeight
     * @return
     */
    public static int calculateInSampleSize(Options options, int reqWidth, int reqHeight) {
        // Raw height and width of image
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {

            // Calculate ratios of height and width to requested height and
            // width
            final int heightRatio = Math.round((float) height / (float) reqHeight);
            final int widthRatio = Math.round((float) width / (float) reqWidth);

            // Choose the smallest ratio as inSampleSize value, this will
            // guarantee
            // a final image with both dimensions larger than or equal to the
            // requested height and width.
            inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
        }
        return inSampleSize;
    }

    public static Bitmap getBitmapFromPath(String image_path, int screenWidth, int screenHeight) {
        Bitmap bitmap = null;
        Options opts = new Options();
        opts.inJustDecodeBounds = true;// 不会真真的去解析图片,只是获取图片的头部信息，宽高等
        BitmapFactory.decodeFile(image_path, opts);
        int scale = BitmapUtil.calculateInSampleSize(opts, screenWidth, screenHeight);
        // 真的解析图片
        opts.inJustDecodeBounds = false;
        opts.inSampleSize = scale;
        bitmap = BitmapFactory.decodeFile(image_path, opts);
        return bitmap;
    }

    /**
     * drawable转bitmap
     *
     * @param drawable
     * @return
     */
    public static Bitmap Drawable2Bitmap(Drawable drawable) {
        BitmapDrawable bd = (BitmapDrawable) drawable;
        Bitmap bm = bd.getBitmap();
        return bm;
    }

    /**
     * 将文件生成位图
     *
     * @param path
     * @return
     * @throws IOException
     */
    @SuppressWarnings("deprecation")
    public static Drawable getDrawable(String path) {
        BitmapDrawable bd = null;
        if (TextUtils.isEmpty(path)) {
            return null;
        }
        try {
            // 打开文件
            File file = new File(path);
            if (!file.exists()) {
                return null;
            }

            ByteArrayOutputStream outStream = new ByteArrayOutputStream();
            byte[] bt = new byte[1024];

            // 得到文件的输入流
            InputStream in = new FileInputStream(file);

            // 将文件读出到输出流中
            int readLength = in.read(bt);
            while (readLength != -1) {
                outStream.write(bt, 0, readLength);
                readLength = in.read(bt);
            }

            // 转换成byte 后 再格式化成位图
            byte[] data = outStream.toByteArray();
            Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, getOptions(1));// 生成位图
            bd = new BitmapDrawable(bitmap);
            in.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return bd;
    }

    /**
     * 根据文件路径获取Bitmap对象
     * @param url
     * @return
     */
    public static Bitmap getBitmapforUrl(String url) {
        Bitmap bm = null;
        if (TextUtils.isEmpty(url)) {
            return null;
        }
        File file = new File(url);
        FileInputStream fs = null;
        try {
            fs = new FileInputStream(file);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        try {
            if (fs != null)
                bm = BitmapFactory.decodeFileDescriptor(fs.getFD(), null, getOptions(1));
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fs != null) {
                try {
                    fs.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        if (bm != null) {
            bm.setDensity(240);
        }

        return bm;
    }

    @SuppressWarnings("deprecation")
    public static Drawable getDrawable(Resources res, int resId) {
        Bitmap bitmap = BitmapFactory.decodeResource(res, resId, getOptions(2));
        return new BitmapDrawable(bitmap);
    }

    private static Options getOptions(int samepleSize) {
        Options bfOptions = new Options();
        bfOptions.inDither = false;
        bfOptions.inPurgeable = true;
        bfOptions.inInputShareable = true;
        bfOptions.inTempStorage = new byte[32 * 1024];
        bfOptions.inSampleSize = samepleSize;
        return bfOptions;
    }

    public static byte[] compressAndBytes(String filepath) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        Options options = new Options();

        // 获取宽，高,不做真实解码
        options.inJustDecodeBounds = true;

        // 解码，注：此时返回的bitmap为空，在options中有图片的真实宽，高
        Bitmap bitmap = BitmapFactory.decodeFile(filepath, options);
        options.inSampleSize = ImageUtil.computeSampleSize(options, 800, 768 * 1024); // 品质
        // 设置做真实解码
        options.inJustDecodeBounds = false;
        // 设置灰度
        options.inPreferredConfig = Config.RGB_565;
        // 设置，解码不占用系统核心内存，随时可以释放
        options.inInputShareable = true;
        options.inPurgeable = true;
        // 真实解码
        // Bitmap bitmap = null;
        try {
            bitmap = BitmapFactory.decodeFile(filepath, options);
        } catch (Exception e) {

        }
        bitmap.compress(CompressFormat.JPEG, 50, baos);
        byte[] imageData = baos.toByteArray();

        // copy 数据
        byte[] result = imageData.clone();
        try {
            baos.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        imageData = null;
        return result;

    }

    /**
     * 读取图片属性：旋转的角度
     *
     * @param path 图片绝对路径
     * @return degree旋转的角度
     */
    public static int readPictureDegree(String path) {
        int degree = 0;
        try {
            ExifInterface exifInterface = new ExifInterface(path);
            int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
            switch (orientation) {
                case ExifInterface.ORIENTATION_ROTATE_90:
                    degree = 90;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    degree = 180;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_270:
                    degree = 270;
                    break;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return degree;
    }

    /*
     * 旋转图片
     *
     * @param angle
     *
     * @param bitmap
     *
     * @return Bitmap
     */
    public static Bitmap rotaingImageView(int angle, Bitmap bitmap) {
        // 旋转图片 动作
        Matrix matrix = new Matrix();
        matrix.postRotate(angle);
        System.out.println("angle2=" + angle);
        // 创建新的图片
        Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
        return resizedBitmap;
    }

    public static Bitmap matrixBitmap(Bitmap bitmap, int picWidth, int viewWidth) {

        Matrix matrix = new Matrix();
        matrix.postScale((float) (viewWidth / picWidth), (float) (viewWidth / picWidth)); // 长和宽放大缩小的比例
        Bitmap resizeBmp = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
        return resizeBmp;

    }

    /**
     * 生成一张不带log的二维码图片
     * @param content  图片地址
     * @param width  宽度
     * @param height  高度
     * @return 生成的二维码图片
     */
/*	public static Bitmap generateBitmap(String content, int width, int height) {
        QRCodeWriter qrCodeWriter = new QRCodeWriter();
		Map<EncodeHintType, String> hints = new HashMap<>();
		hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
		try {
			BitMatrix encode = qrCodeWriter.encode(content, BarcodeFormat.QR_CODE, width, height, hints);
			int[] pixels = new int[width * height];
			for (int i = 0; i < height; i++) {
				for (int j = 0; j < width; j++) {
					if (encode.get(j, i)) {
						pixels[i * width + j] = 0x00049d4d;
					} else {
						pixels[i * width + j] = 0xffffffff;
					}
				}
			}
			return Bitmap.createBitmap(pixels, 0, width, width, height, Bitmap.Config.RGB_565);
		} catch (WriterException e) {
			e.printStackTrace();
		}
		return null;
	}*/

    /**
     * 生成一张带logo的二维码图片
     *
     * @param qrBitmap   二维码图片
     * @param logoBitmap logo
     * @return 生成的带logo的二维码图片
     */
    public static Bitmap addLogo(Bitmap qrBitmap, Bitmap logoBitmap) {
        int qrBitmapWidth = qrBitmap.getWidth();
        int qrBitmapHeight = qrBitmap.getHeight();
        int logoBitmapWidth = logoBitmap.getWidth();
        int logoBitmapHeight = logoBitmap.getHeight();
        Bitmap blankBitmap = Bitmap.createBitmap(qrBitmapWidth, qrBitmapHeight, Config.ARGB_8888);
        Canvas canvas = new Canvas(blankBitmap);
        canvas.drawBitmap(qrBitmap, 0, 0, null);
        canvas.save(Canvas.ALL_SAVE_FLAG);
        float scaleSize = 1.0f;
        while ((logoBitmapWidth / scaleSize) > (qrBitmapWidth / 5) || (logoBitmapHeight / scaleSize) > (qrBitmapHeight / 5)) {
            scaleSize *= 2;
        }
        float sx = 1.0f / scaleSize;
        canvas.scale(sx, sx, qrBitmapWidth / 2, qrBitmapHeight / 2);
        canvas.drawBitmap(logoBitmap, (qrBitmapWidth - logoBitmapWidth) / 2, (qrBitmapHeight - logoBitmapHeight) / 2, null);
        canvas.restore();
        return blankBitmap;
    }
}
